using CMS.Common;
using CMS.EFCore;
using CMS.Entity;
using CMS.Service;
using CMS.Web.Attributes;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;

namespace CMS.Web.Controllers;

public class ArticleController(
    IArticleService articleService,
    IArticleCategoryService articleCategoryService,
    IMemoryCache memoryCache,
    IWebHostEnvironment webHostEnvironment,
    MyDbContext myDbContext,
    IArticleCommentService articleCommentService,
    ISensitiveWordService sensitiveWordService) : Controller {
    // GET
    public IActionResult Index() {
        return View();
    }

    public async Task<IActionResult> GetArticles(int pageIndex, int pageSize) {
        var articles = await articleService
                             .GetPage(pageIndex + 1, pageSize, out int total, a => a.IsDeleted == false, a => a.Id,
                                 true)
                             .Select(a => new {
                                 a.Id,
                                 a.Title,
                                 a.Author,
                                 a.Origin,
                                 CreateTime = a.CreatedDate,
                                 CategoryName = a.ArticleCategory!.ArticleCategoryName
                             }).ToListAsync();
        return Json(new { total, data = articles });
    }

    public IActionResult ShowAdd() {
        return View();
    }

    public async Task<IActionResult> GetArticleCategories() {
        //构建缓存
        var articleCategories = await memoryCache.GetOrCreateAsync("ArticleCategories",
            async _ => await articleCategoryService.Get(ac => ac.IsDeleted == false).ToListAsync());
        return Json(new
            { code = 200, data = articleCategories });
    }

    [HttpPost]
    public async Task<IActionResult> FileUpload(string? waterMark, IFormFile? file) {
        if (file == null || file.Length == 0) {
            return Json(new { code = 400, error = "No file uploaded" });
        }

        var url = await articleService.UploadFile(file, waterMark, webHostEnvironment.WebRootPath);
        return Json(new { code = 200, url });
    }

    [HttpPost]
    [UnitOfWork]
    public async Task<IActionResult> AddArticle(Article article, int articleCategory) {
        article.ArticleCategoryId = articleCategory;
        article.CreatedDate = DateTime.Now;
        article.EditDate = DateTime.Now;
        article.IsDeleted = false;

        await articleService.AddAsync(article);
        await myDbContext.SaveChangesAsync();
        //生成静态页面
        await articleService.CreateStaticHtml(webHostEnvironment.WebRootPath, article);
        return Json(new { code = 200, msg = "Article added successfully" });
    }
    
    //一键构建所有静态页面
    public async Task<IActionResult> CreateStaticHtmlForAllArticles() {
        var articles = await articleService.Get(a => a.IsDeleted == false).ToListAsync();
        foreach (Article article in articles) {
            await articleService.CreateStaticHtml(webHostEnvironment.WebRootPath, article);
        }
        return Json(new { code = 200, msg = "ArticleHtml created successfully" });
    }
    
    //添加评论
    [HttpPost]
    [UnitOfWork]
    public async Task<IActionResult> AddArticleComment([FromBody]ArticleComment articleComment) {
        if (string.IsNullOrEmpty(articleComment.Msg)) {
            return Json(new { code = 400, error = "No message uploaded" });
        }
        
        (bool result, string? msg) = await sensitiveWordService.FilterSensitiveWords(articleComment);

        return Json(!result ? new { code = 400, msg } : new { code = 200, msg });
    }
    
    //获取评论
    public async Task<IActionResult> GetArticleComments(int articleId) {
        return Json(new { code = 200, data = await articleCommentService.Get(ac => ac.ArticleId == articleId).ToListAsync() });
    }
    
    //获取阅读量
    public async Task<IActionResult> GetArticleHits(int? articleId) {
        if (articleId == null) {
            return Json(new { code = 400, error = "No article selected" });
        }
        ArticleHitCounter.HitsAdd(articleId.Value);
        return Json(new { code = 200, hits = await articleService.Get(a => a.Id == articleId).Select(a => a.Hits).FirstOrDefaultAsync()});
    }
}